﻿namespace IntellectShop.Web2.Hardware.Controllers
{
	using System;
	using System.Configuration;
	using System.Security.Principal;
	using System.Web.Mvc;
	using System.Web.Routing;
	using System.Web.Security;
	using IntellectShop.Web2.Hardware.Models;
	using IntellectShop.Web2.Hardware.ViewModels;
	using IntellectShop.Common;

	[IntellectShop.Web2.Hardware.Code.NoCache]
	[IntellectShop.Web2.Hardware.Code.HandleErrorWithELMAH]
	public class AccountController : Controller
	{
		public IFormsAuthenticationService FormsService { get; private set; }

		public IMembershipService MembershipService { get; private set; }

		public IRoleService RoleService { get; private set; }

		protected override void Initialize(RequestContext requestContext)
		{
			if (this.FormsService == null) { this.FormsService = new FormsAuthenticationService(); }
			if (this.MembershipService == null) { this.MembershipService = new AccountMembershipService(); }
			if (this.RoleService == null) { this.RoleService = new RoleService(); }

			base.Initialize(requestContext);
		}

		// **************************************
		// URL: /Account/LogOn
		// **************************************

		public ActionResult LogOn()
		{
			return View();
		}

		[HttpPost]
		public ActionResult LogOn(LogOnModel model, string returnUrl)
		{
			if (ModelState.IsValid)
			{
				if (this.MembershipService.ValidateUser(model.UserName, model.Password))
				{
					this.MigrateShoppingCart(model.UserName);

					this.FormsService.SignIn(model.UserName, model.RememberMe);
					if (!String.IsNullOrEmpty(returnUrl))
					{
						return Redirect(returnUrl);
					}
					else
					{
						return RedirectToAction("AboutCompany", "Home");
					}
				}
				else
				{
					ModelState.AddModelError("", "Имя пользователя или пароль некорректны.");
				}
			}

			// If we got this far, something failed, redisplay form
			return View(model);
		}

		// **************************************
		// URL: /Account/LogOff
		// **************************************

		public ActionResult LogOff()
		{
			this.FormsService.SignOut();

			return Redirect(Request.UrlReferrer.ToString());
		}

		// **************************************
		// URL: /Account/Register
		// **************************************

		public ActionResult Register()
		{
			ViewData["PasswordLength"] = this.MembershipService.MinPasswordLength;
			ViewData["NumNonAlphaNumerics"] = this.MembershipService.MinNonAplhaNumerics;
			return View();
		}

		[HttpPost]
		public ActionResult Register(RegisterModel model)
		{
			if (ModelState.IsValid)
			{
				// Attempt to register the user
				MembershipCreateStatus createStatus = this.MembershipService.CreateUser(model.UserName, model.Password, model.Email);
				if (createStatus == MembershipCreateStatus.Success)
				{
					this.PublishAdministratorRole(model.UserName);
					this.MigrateShoppingCart(model.UserName);

					this.FormsService.SignIn(model.UserName, false /* createPersistentCookie */);
					return RedirectToAction("AboutCompany", "Home");
				}
				else
				{
					ModelState.AddModelError("", AccountValidation.ErrorCodeToString(createStatus));
				}
			}

			// If we got this far, something failed, redisplay form
			ViewData["PasswordLength"] = this.MembershipService.MinPasswordLength;
			ViewData["NumNonAlphaNumerics"] = this.MembershipService.MinNonAplhaNumerics;

			return View(model);
		}

		private void PublishAdministratorRole(string userName)
		{
			//тут надо создать роль Administrator, если ее нет
			if (!this.RoleService.RoleExists(Globals.AdministratorRoleName))
			{
				this.RoleService.CreateRole(Globals.AdministratorRoleName);
			}

			//проверим есть ли user в списке админови выдадим ему эту роль, если он там
			string administrators = ConfigurationManager.AppSettings["Administrators"];
			if (!String.IsNullOrEmpty(administrators))
			{
				foreach (var item in administrators.Split(' ', ','))
				{
					if (!String.IsNullOrEmpty(item))
					{
						if (item.Equals(userName, StringComparison.InvariantCultureIgnoreCase))
						{
							this.RoleService.AddUserToRole(userName, Globals.AdministratorRoleName);
						}
					}
				}
			}
		}

		private void MigrateShoppingCart(string UserName)
		{
			// Associate shopping cart items with logged-in user
			var cart = Common.Cart.CreateCart(this.HttpContext);

			cart.MigrateCart(UserName);
			Common.Globals.SetOwnerID(this.HttpContext, UserName);
		}

		// **************************************
		// URL: /Account/ChangePassword
		// **************************************

		[Authorize]
		public ActionResult ChangePassword()
		{
			ViewData["PasswordLength"] = this.MembershipService.MinPasswordLength;
			ViewData["NumNonAlphaNumerics"] = this.MembershipService.MinNonAplhaNumerics;
			return View();
		}

		[Authorize]
		[HttpPost]
		public ActionResult ChangePassword(ChangePasswordModel model)
		{
			if (ModelState.IsValid)
			{
				if (this.MembershipService.ChangePassword(User.Identity.Name, model.OldPassword, model.NewPassword))
				{
					return RedirectToAction("ChangePasswordSuccess");
				}
				else
				{
					ModelState.AddModelError("", "Текущий пароль неверный или новый пароль неправильный.");
				}
			}

			// If we got this far, something failed, redisplay form
			ViewData["PasswordLength"] = this.MembershipService.MinPasswordLength;
			ViewData["NumNonAlphaNumerics"] = this.MembershipService.MinNonAplhaNumerics;
			return View(model);
		}

		// **************************************
		// URL: /Account/ChangePasswordSuccess
		// **************************************

		public ActionResult ChangePasswordSuccess()
		{
			return View();
		}

		// ***************************************
		// Admin action
		// ***************************************
		[Authorize(Roles = Globals.AdministratorRoleName)]
		public ActionResult Admin()
		{
			AdminViewModel viewModel = new AdminViewModel
			{
				Users = this.MembershipService.GetAllUsers(),
				Roles = this.RoleService.GetAllRoles()
			};

			return View(viewModel);
		}

		[Authorize(Roles = Globals.AdministratorRoleName)]
		public ActionResult DeleteRole(string role)
		{
			if (RoleService.RoleExists(role))
			{
				// Cannot delete the Admin role
				//
				if (role == Globals.AdministratorRoleName)
				{
					TempData["RoleError"] = "Не могу удалить роль: '" + Globals.AdministratorRoleName + "'.";
				}
				else
				{
					// Remove the role from all users
					//
					try
					{
						string[] userNames = RoleService.GetUsersInRole(role);
						if (userNames != null && userNames.Length > 0)
						{
							RoleService.RemoveUsersFromRole(userNames, role);
						}

						// Delete the role
						//
						try
						{
							if (!RoleService.DeleteRole(role, true))
							{
								TempData["RoleError"] = "Не могу удалить роль.";
							}
						}
						catch (Exception)
						{
							TempData["RoleError"] = "Не могу удалить роль.";
						}
					}
					catch (Exception)
					{
						TempData["RoleError"] = "Не могу удалить пользователей из роли.";
					}
				}
			}

			return RedirectToAction("Admin");
		}

		[Authorize(Roles = Globals.AdministratorRoleName)]
		public ActionResult AddRole(string newRole)
		{
			if (String.IsNullOrEmpty(newRole))
			{
				TempData["RoleError"] = "Название роли пустое.";
			}
			else if (RoleService.RoleExists(newRole))
			{
				TempData["RoleError"] = "Роль уже существует.";
			}
			else
			{
				RoleService.CreateRole(newRole);
			}

			return RedirectToAction("Admin");
		}

		[Authorize(Roles = Globals.AdministratorRoleName)]
		public ActionResult ToggleRole(string role, string userName)
		{
			try
			{
				MembershipUser user = MembershipService.GetUser(userName, false);
				if (user != null)
				{
					if (RoleService.RoleExists(role))
					{
						if (role == Globals.AdministratorRoleName && userName == HttpContext.User.Identity.Name)
						{
							TempData["UserError"] = "Нельзя удалить себя из роли '" + Globals.AdministratorRoleName + "'.";
						}
						else
						{
							if (RoleService.IsUserInRole(userName, role))
							{
								try
								{
									RoleService.RemoveUserFromRole(userName, role);
								}
								catch (Exception)
								{
									TempData["UserError"] = "Не смог удалить пользователя из роли.";
								}
							}
							else
							{
								try
								{
									RoleService.AddUserToRole(userName, role);
								}
								catch (Exception)
								{
									TempData["UserError"] = "Не смог добавить пользователя в роль.";
								}
							}
						}
					}
					else
					{
						TempData["UserError"] = "Роль не существует.";
					}
				}
			}
			catch (Exception)
			{
				TempData["UserError"] = "Не нашел пользователя.";
			}

			return RedirectToAction("Admin");
		}

		[Authorize(Roles = Globals.AdministratorRoleName)]
		public ActionResult UnlockUser(string userName)
		{
			try
			{
				MembershipUser user = MembershipService.GetUser(userName, false);

				if (!user.UnlockUser())
				{
					TempData["UserError"] = "Не смог разблокировать пользователя.";
				}
			}
			catch (Exception)
			{
				TempData["UserError"] = "Не смог найти пользователя.";
			}

			return RedirectToAction("Admin");
		}

		[Authorize(Roles = Globals.AdministratorRoleName)]
		public ActionResult ToggleApproved(string userName)
		{
			if (userName == User.Identity.Name)
			{
				TempData["UserError"] = "Вы не можете деактивировать себя.";
			}
			else
			{
				try
				{
					MembershipUser user = MembershipService.GetUser(userName, false);
					user.IsApproved = !user.IsApproved;
					try
					{
						MembershipService.UpdateUser(user);
					}
					catch (Exception)
					{
						TempData["UserError"] = "Не могу изменить информацию о пользователе.";
					}
				}
				catch (Exception)
				{
					TempData["UserError"] = "Не нашел пользователя.";
				}
			}

			return RedirectToAction("Admin");
		}

		[Authorize(Roles = Globals.AdministratorRoleName)]
		public ActionResult ResetPassword(string userName)
		{
			try
			{
				string newPassword;
				MembershipService.ResetPassword(userName, out newPassword);

				try
				{
					string storeEmail = ConfigurationManager.AppSettings["StoreEmail"];
					string managerEmail = ConfigurationManager.AppSettings["ManagerEmail"];
					string forceUsePickupDirectory = ConfigurationManager.AppSettings["ForceUsePickupDirectory"];
					if (!String.IsNullOrEmpty(forceUsePickupDirectory))
					{
						forceUsePickupDirectory = Server.MapPath(forceUsePickupDirectory);
					}

					MailUtils.Send(
						storeEmail,
						MembershipService.GetUserEmail(userName),
						Server.MapPath("~/App_Data/MailTemplates/resetPasswordTemplate.htm"),
						"windows-1251",
						String.Format("Новый пароль: {0}", newPassword),
						userName,
						forceUsePickupDirectory,
						managerEmail);
				}
				catch(Exception)
				{
					TempData["UserError"] = "Не могу отправить email пользователю. Новый пароль пользователя: " + newPassword;
				}
			}
			catch (Exception)
			{
				TempData["UserError"] = "Не могу найти пользователя.";
			}

			return RedirectToAction("Admin");
		}

		[Authorize(Roles = Globals.AdministratorRoleName)]
		public ActionResult DeleteUser(string userName)
		{
			if (userName == User.Identity.Name)
			{
				TempData["UserError"] = "Вы не можете удалить себя.";
			}
			else
			{
				if (!MembershipService.DeleteUser(userName, true))
				{
					TempData["UserError"] = "Не могу удалить пользователя.";
				}
			}

			return RedirectToAction("Admin");
		}

		protected override void OnActionExecuting(ActionExecutingContext filterContext)
		{
			if (filterContext.HttpContext.User.Identity is WindowsIdentity)
			{
				throw new InvalidOperationException("Windows authentication is not supported.");
			}

			// Register activity for the user.
			Membership.GetUser(User.Identity.Name, true);
		}
	}
}
